#pragma once
#include "DXAMLCommon.h"


#include <xmllite.h>
#include "Scanner.h"


class ReferenceCountedBase;



class YReader :
	public ReferenceCountedBase,
	public IXmlReader
{

private: 
	YReader(const YReader &);
public: 
	YReader(struct IMalloc * pMalloc);
	virtual ~YReader();
	void Initialize(bool);
	void Reset();


	//IXmlReader
	virtual HRESULT __stdcall QueryInterface(const struct _GUID & riid, void * * ppvObject);
	virtual unsigned long __stdcall AddRef();
	virtual unsigned long __stdcall Release();
	virtual HRESULT __stdcall SetInput(struct IUnknown * pUnknown);
	virtual HRESULT __stdcall GetProperty(XUINT32 nProperty, HRESULT * ppValue);
	virtual HRESULT __stdcall SetProperty(XUINT32 nProperty, HRESULT pValue);
	virtual HRESULT __stdcall Read(enum XmlNodeType * pNodeType);
	virtual HRESULT __stdcall GetNodeType(enum XmlNodeType * pNodeType);
	virtual HRESULT __stdcall MoveToFirstAttribute();
	virtual HRESULT __stdcall MoveToNextAttribute();
	virtual HRESULT __stdcall MoveToAttributeByName(const wchar_t * pwszLocalName, const wchar_t * pwszNamespaceUri);
	virtual HRESULT __stdcall MoveToElement();
	virtual HRESULT __stdcall GetQualifiedName(const wchar_t * * ppwszQualifiedName, XUINT32 * pcwchQualifiedName);
	virtual HRESULT __stdcall GetNamespaceUri(const wchar_t * * ppwszNamespaceUri, XUINT32 * pcwchNamespaceUri);
	virtual HRESULT __stdcall GetLocalName(const wchar_t * * ppwszLocalName, XUINT32 * pcwchLocalName);
	virtual HRESULT __stdcall GetPrefix(const wchar_t * * ppwszPrefix, XUINT32 * pcwchPrefix);
	virtual HRESULT __stdcall GetValue(const wchar_t * * ppwszValue, XUINT32 * pcwchValue);
	virtual HRESULT __stdcall ReadValueChunk(wchar_t * pwchBuffer, XUINT32 cwchChunkSize, XUINT32 * pcwchRead);
	virtual HRESULT __stdcall GetBaseUri(const wchar_t * * ppwszBaseUri, XUINT32 * pcwchBaseUri);
	virtual XINT32 __stdcall IsDefault();
	virtual XINT32 __stdcall IsEmptyElement();
	virtual HRESULT __stdcall GetLineNumber(XUINT32 * pnLineNumber);
	virtual HRESULT __stdcall GetLinePosition(XUINT32 * pnLinePosition);
	virtual HRESULT __stdcall GetAttributeCount(XUINT32 * pnAttributeCount);
	virtual HRESULT __stdcall GetDepth(XUINT32 * pnDepth);
	virtual XINT32 __stdcall IsEOF();

private: 
	void operator=(const YReader &);
	void ResetStart();
	void ResetEnd();
	void HandleException(HRESULT hr);
	enum XmlConformanceLevel GetConformanceLevel();
	void SetConformanceLevel(enum XmlConformanceLevel);
	bool GetRandomAccess();
	void SetRandomAccess(bool);
	enum DtdProcessing GetDtdProcessing();
	void SetDtdProcessing(enum DtdProcessing);
	void GetTokenData(struct StringPtr * pData);
	void GetTokenData2(struct StringPtr * pData, struct StringPtr * pSwap);
	void GetTokenData3(struct StringPtr * pData, struct StringPtr * pSwap);
	void GetTokenName(struct StringPtr * pName);
	void GetTokenQName(struct StringPtr * pQName, struct StringPtr * pPrefix);
	void SetTokenData(wchar_t, struct StringPtr *);
	void SetTokenData(struct StringPtr * pInput, struct StringPtr * pData);
	void SetTokenData2(wchar_t, struct StringPtr *);
	void SetTokenData2(struct StringPtr * pInput, struct StringPtr * pData);
	void SetTokenData3(wchar_t wh, struct StringPtr * pData);
	void SetTokenData3(struct StringPtr *, struct StringPtr *);
	void SetTokenChar(wchar_t, struct StringPtr *);
	//void(none)(* function)() *
	void ParseElement();
	void ParseAttributes();
	void ParseAttributesN();
	void ParseAttributesS();
	void ParseAttributeValue(bool fChunking);
	void ParseCdSect();
	void ParseComment();
	void ParseCommentSubset();
	void ParseContent();
	void ParseDeclAttlist();
	void ParseDeclAttlistDefault(DeclAttDef * pAttDef);
	void ParseDeclAttlistEnumeratedType(DeclAttDef * pAttDef);
	void ParseDeclAttlistType(DeclAttDef * pAttDef);
	void ParseDeclDoctype();
	void ParseDeclElement();
	void ParseDeclElementCp(DeclElement * pElement);
	void ParseDeclElementCpEnd(DeclElement * pElement);
	void ParseDeclEntity();
	void ParseDeclEntityValue(DeclEntity * pEntity);
	void ParseDeclNotation();
	void ParseDeclExternalId(struct StringPtr * pPublicId, struct StringPtr * pSystemId, bool fNotation);
	void ParseAfterDocumentType();
	void ParseDocument();
	void ParseDocumentEnd();
	void ParseDtdExternal();
	void ParseElementN();
	void ParseElementND();
	void ParseTagEnd();
	void ParseTagEndS();
	void ParseEETagEnd();
	void ParseEETagEndS();
	void ParseEmptyElement();
	void ParseEndElement();
	bool ParseEntityRef();
	bool ParseEntityRefEnd();
	void ParseEpilog();
	void ParseError();
	void ParsePi();
	void ParsePiData();
	void ParsePiSubset();
	void ParseProlog();
	void ParseFragmentProlog();
	void ParseSubsetExternal();
	void ParseSubsetIgnore();
	void ParseSubsetInternal();
	void ParseTextDecl();
	void ParseXmlDecl();
	void ParseAfterXmlDecl();
	enum XmlNodeType ParseCharRef();
	enum XmlNodeType ParseTextOrWhitespaceValue(bool fFailOnEntities);
	bool ParseTextOrWhitespaceNode(bool fFailOnEntities);
	HRESULT SkipRestOfValue();
	struct Element
	{
		struct StringPtr qname;
		struct StringPtr uri;
		struct StringPtr lname;
		XINT32 nContext;
		bool fEmpty;
		enum XmlNodeType nodeType;

	};
private: 
	void ReportNone();
	void ReportElement(struct YReader::Element * pelement);
	void ReportAttribute(struct Attribute *);
	void ReportText();
	void ReportCDATA();
	void ReportProcessingInstruction(struct StringPtr * pstrName);
	void ReportComment();
	void ReportDocumentType(struct YReader::Element * pelement, struct StringPtr * pstrPrefix, struct StringPtr * pstrQualifiedName, struct StringPtr * pstrPublicId, struct StringPtr * pstrSystemId);
	void ReportWhitespace();
	void ReportEndElement(struct YReader::Element * pelement);
	void ReportXmlDeclaration(struct YReader::Element * pelement, struct StringPtr * pstrVersion, struct StringPtr * pstrEncoding, enum XmlStandalone standalone);
	void AddAttribute(struct StringPtr * pstrQualifiedName, struct StringPtr * pstrLocalName, struct StringPtr * pstrPrefix, struct StringPtr * pstrNamespaceUri, struct StringPtr * pstrValue);
	bool IsElementLikeNodeType(enum XmlNodeType);
	XINT32 GetTokenDeclInner();
	XINT32 GetTokenDeclOuter();
	XINT32 GetTokenDeclLiteral(DeclEntity * pentityContaining);
	bool HandleParameterEntityReference(DeclEntity * pentityContaining, bool fInnerParamRef);
	DeclEntity * HandleEntity(DeclEntity * pentityContaining, DeclEntity * pEntity, void * pScope);
	DeclEntity * HandleEntityEnd(void * pScope);
	DeclEntity * CheckEntity(struct StringPtr * pName, bool fAttValue);
	DeclEntity * CheckParamEntity(struct StringPtr *);
	void CheckCharEntity(struct StringPtr * pName);
	struct Attribute * CheckNsAttribute(struct StringPtr * pName);
	void ProcessAttributesN();
	void ProcessXmlSpaceAttribute(struct Attribute * pattribute);
	void HashAttributesForAttDefs();
	struct Attribute * FindAttributeByQName(struct StringPtr * pstrAttributeQName);
	void GraftAttDefs(_stack<DeclAttDef *,4> * pAttDefs);
	void GraftAttDefsN(_stack<DeclAttDef *,4> *);
	void GraftNsAttDefsN(_stack<DeclAttDef *,4> * pAttDefs);
	void NormalizeAttributeValue(struct StringPtr * pAttributeValue);
	void ExpandAttributeValue(struct StringPtr * pAttributeValue, struct StringPtr * pEntityName, struct StringPtr * pDest);
	void FillAttributeValue(struct StringPtr *, struct StringPtr *, struct StringPtr *);
	void TrimAndCollapseAttributeValue(struct StringPtr * pAttributeValue);
	struct StringPtr * GetCurrentBaseUri();
	XINT32 ComputeAttributeHash(struct Attribute *);
	void ResetValue();
	HRESULT ReadNextAvailableValueChunk();
	void CheckMaxElementDepth();
	void IncrementAndCheckResolved3CharEntities(XUINT32);
	Scanner _scanner;
private: 
	BlockAlloc _alloc;
	_stack<InputSource *,4> _inputSources;
	NamespaceSupport _nsSupport;
	DeclDoctype _doctype;

	//void(none)(* function)() * _pfnParse;
	//void(none)(* function)() * _pfnParseNext;
	//void(none)(* function)() * _pfnParseElement;
	//void(none)(* function)() * _pfnParseAttributes;

	struct StringPtr _qualifiedName;
	struct StringPtr _prefix;
	struct StringPtr _namespaceUri;
	struct StringPtr _localName;
	struct StringPtr _value;
	StringBuilder _valueBuilder;
	bool _fValueRead;
	bool _fValueInValueBuilder;
	enum XmlNodeType _nodeType;
	HRESULT _hr;
	bool _fWhitespace;
	bool _fDirty;
	bool _fDefaultAttribute;
	bool _fEmptyElement;
	bool _fStandalone;
	enum XmlConformanceLevel _xclConformanceLevel;
	bool _fParsingAsFragment;
	bool _fRandomAccess;
	bool _fMoreData;
	bool _fParamEntityRef;
	bool _fParamEntitySkipped;
	enum DtdProcessing _dtdpDtdProcessing;
	XUINT32 _nMaxElementDepth;
	XUINT32 _nMaxResolvedEntities;
	XUINT32 _nResolved3CharEntities;
	enum XmlReadState _readState;
	bool _fEOF;
	void * _pScope;
	void * _pAttributesScope;
	XINT32 _nExternalMarkup;
	_stack<YReader::Element,16> _elements;
	struct YReader::Element * _pElement;
	XUINT32 _nAttribute;
	XUINT32 _nDefAtts;
	XUINT32 _hashSeed;
	XUINT32 _nChunkSize;
	_stack<Attribute,16> _attributes;
	_stack<Attribute *,16> _nsAttributes;
	bool _posChanged;
	struct Position _posSaved;
	struct Position _attributePosition;
	_stack<AttValueToken,16> _attValueTokens;
	_stack<unsigned int,16> _attIndices;
	_reference<IXmlResolver> _pResolver;
	_reference<IMultiLanguage2> _pMultiLanguage;
	wchar_t _whChar[2];
};